package jqueryadmin;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.logging.Logger;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

public class MainServlet extends HttpServlet {
	private static final long serialVersionUID = 2362794833292017908L;
	Logger logger = Logger.getLogger("indexServlet");

	public MainServlet() {
		super();
	}

	private class PostData {
		public byte[] data;
		public String fileName;
	}

	public byte[] readData(HttpServletRequest request) throws IOException {
		InputStream is = request.getInputStream();
		byte[] data = new byte[request.getContentLength()];
		int rd = is.read(data);
		while (rd < data.length && rd != -1) {
			rd = is.read(data, rd, data.length - rd);
		}
		is.close();
		return data;
	}

	private PostData extractData(HttpServletRequest request) throws IOException {
		InputStream is = request.getInputStream();
		byte[] data = readData(request);
		is.read(data);
		is.close();

		int beginSliceIndex = 0;
		int endSliceIndex = data.length - getBoundary(request).length() - 9;

		final int CR = (byte) '\r';
		final int LF = (byte) '\n';

		for (int i = 0; i < data.length; i++) {
			if (data[i] == CR && data[i + 1] == LF && data[i + 2] == CR
					&& data[i + 3] == LF) {
				beginSliceIndex = i + 4;
				break;
			}
		}

		PostData postData = new PostData();

		postData.data = new byte[endSliceIndex - beginSliceIndex + 1];
		for (int i = beginSliceIndex; i <= endSliceIndex; i++) {
			postData.data[i - beginSliceIndex] = data[i];
		}

		final String strFn = "filename=\"";

		String str = new String(data, 0, beginSliceIndex);
		int ind1 = str.indexOf(strFn) + strFn.length();
		int ind2 = str.substring(ind1).indexOf('\"');
		postData.fileName = str.substring(ind1, ind1 + ind2);
		return postData;
	}

	/**
	 * get boundary
	 * 
	 * @param request
	 *            - Request to server
	 */
	private String getBoundary(HttpServletRequest request) {
		String cType = request.getContentType();
		return cType.substring(cType.indexOf("boundary=") + 9);
	}

	/**
	 * get request to server
	 * 
	 * @param request
	 *            - Request to server
	 * @param response
	 *            - Response from server
	 */
	protected void doGet(HttpServletRequest request,
			HttpServletResponse response) throws ServletException, IOException {
		response.setContentType("text/plain");
		response.setCharacterEncoding("UTF-8");
		try {
			if (request.getParameter("download") != null) {
				downloadWSDL(request.getParameter("download"), response);
			} else {
				response.setContentType("text/html");
				showPage(response);
			}
		} catch (Exception e) {
			logger.severe(e.getMessage());
		}
	}

	/**
	 * post request to server
	 * 
	 * @param request
	 *            - Request to server
	 * @param response
	 *            - Response from server
	 */
	protected void doPost(HttpServletRequest request,
			HttpServletResponse response) throws ServletException, IOException {
		response.setContentType("text/plain");
		response.setCharacterEncoding("UTF-8");
		try {
			if (request.getParameter("update") != null) {
				updateWSDL(request, response);
			} else if (request.getParameter("download") != null) {
				downloadWSDL(request.getParameter("download"), response);
			} else if (request.getParameter("upload") != null) {
				uploadWSDL(request, response);
			} else {
				showPage(response);
			}
		} catch (Exception e) {
			logger.severe(e.getMessage());
		}
	}

	private void showPage(HttpServletResponse response) throws IOException {
		PrintWriter pw = response.getWriter();
		pw.write("<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Transitional//EN\" \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd\">");
		pw.write("<html xmlns=\"http://www.w3.org/1999/xhtml\">");
		pw.write("<head>");
		pw.write("<meta http-equiv=\"Content-Type\" content=\"text/html; charset=UTF-8\" />");
		pw.write("<title>Swordfish Registry Admin Tool Servlet</title>");
		pw.write("</head>");
		pw.write("<body>");
		pw.write("Please open <a href=\"/registry/jQuery-admin.html\">admin page</a>");
		pw.write("</body>");
		pw.write("</html>");
	}

	/**
	 * Return WSDL file from Service Registry by file name
	 * 
	 * @param fileName
	 *            - name of file which placed in Service Reistry
	 * @param response
	 *            - Response from server
	 * @throws IOException
	 */
	private void downloadWSDL(String fileName, HttpServletResponse response)
			throws IOException {
		logger.info("Download WSDL file " + fileName);
		PrintWriter rw = response.getWriter();
		try {
			String s = "";
			URL url = new URL("http://localhost:9001/registry/wsdl/" + fileName);
			HttpURLConnection conn = (HttpURLConnection) url.openConnection();
			conn.setRequestProperty("Accept", "text/plain");
			BufferedReader reader = new BufferedReader(new InputStreamReader(
					conn.getInputStream()));
			response.setContentType("application/octet-stream");
			response.addHeader("Content-Disposition", "attachment; filename="
					+ fileName);
			while ((s = reader.readLine()) != null) {
				rw.write(s + "\n");
			}
			reader.close();
		} catch (Exception ex) {
			rw.write("error");
		}
	}

	/**
	 * Upload WSDL file to Service Registry
	 * 
	 * @param request
	 *            - Request to server
	 * @param response
	 *            - Response from server
	 * @throws IOException
	 */
	private void uploadWSDL(HttpServletRequest request,
			HttpServletResponse response) throws IOException {
		logger.info("Uploading WSDL File");
		PrintWriter rw = response.getWriter();
		try {
			PostData dataSlice = extractData(request);
			int i;
			String wsdl = "";
			for (i = 0; i < dataSlice.data.length - 1; i++) {
				wsdl += String.valueOf((char) dataSlice.data[i]);
			}
			URL url = new URL("http://localhost:9001/registry/wsdl/"
					+ dataSlice.fileName);
			HttpURLConnection urlConnect = (HttpURLConnection) url
					.openConnection();
			urlConnect.setInstanceFollowRedirects(false);
			urlConnect.setDoOutput(true);
			urlConnect.setRequestMethod("PUT");

			urlConnect.setRequestProperty("Content-Length", String.valueOf(wsdl
					.length()));
			urlConnect.setRequestProperty("Content-Type",
					"application/xml; charset=UTF-8");
			urlConnect.connect();
			OutputStream os = urlConnect.getOutputStream();
			os.write(wsdl.getBytes());
			os.close();
			urlConnect.getResponseCode();
			rw.write("ok");
		} catch (Exception ex) {
			rw.write("error");
		}
	}

	/**
	 * Update WSDL File in Service Registry. Get file name and text and
	 * uploading to Service Registry.
	 * 
	 * @param request
	 *            - Request to server
	 * @param response
	 *            - Response from server
	 * @throws IOException
	 */
	private void updateWSDL(HttpServletRequest request,
			HttpServletResponse response) throws IOException {
		logger.info("Update WSDL File");
		PrintWriter rw = response.getWriter();
		try {
			String wsdl = request.getParameter("text");
			URL url = new URL("http://localhost:9001/registry/wsdl/"
					+ request.getParameter("update"));
			HttpURLConnection urlConnect = (HttpURLConnection) url
					.openConnection();
			urlConnect.setInstanceFollowRedirects(false);
			urlConnect.setDoOutput(true);
			urlConnect.setRequestMethod("PUT");

			urlConnect.setRequestProperty("Content-Length", String.valueOf(wsdl
					.length()));
			urlConnect.setRequestProperty("Content-Type",
					"application/xml; charset=UTF-8");
			urlConnect.connect();
			OutputStream os = urlConnect.getOutputStream();
			os.write(wsdl.getBytes());
			os.close();
			urlConnect.getResponseCode();
			rw.write("ok");
		} catch (Exception ex) {
			rw.write("error");
		}
	}
}
